package avicit.bdp.dlm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.datasource.BaseDataSource;
import avicit.bdp.common.service.dto.CommonTypeDTO;
import avicit.bdp.common.service.dto.DataSourceDTO;
import avicit.bdp.common.service.service.CommonTypeService;
import avicit.bdp.common.service.service.DataSourceService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.DESUtils;
import avicit.bdp.common.utils.database.DBUtils;
import avicit.bdp.common.utils.database.adapter.DbAdapter;
import avicit.bdp.common.utils.database.adapter.DbAdapterUtils;
import avicit.bdp.common.utils.enums.CommonTypeEnums;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dlm.dao.DlmDataSourceDao;
import avicit.bdp.dlm.dto.DlmDataSourceDTO;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 统计服务
 *
 * @author xugb
 * @date 2020/12/1 9:22
 */
@Service
public class DlmDataSourceService extends BaseService<DlmDataSourceDao, DlmDataSourceDTO> {

  @Autowired private DataSourceService dataSourceService;

  @Autowired private CommonTypeService commonTypeService;

  /**
   * 按类型统计数据湖存储接入总数
   *
   * @param typeIdList 类型ID集合
   * @return 数据数存储接入总数
   */
  int countLakeDataSourceByType(List<String> typeIdList) {
    return this.mapper.countLakeDataSourceByType(typeIdList);
  }

  /**
   * 按数据类型结构统计数据湖存储接入总数
   *
   * @param type 数据类型结构
   * @return 数据数存储接入总数
   */
  int countLakeDataSourceByStructure(Integer type) {
    return this.mapper.countLakeDataSourceByStructure(type);
  }

  /**
   * 查询数据源分类，已去重
   *
   * @return 数据源分类
   */
  List<String> selectLakeDataSourceTypeId() {
    return this.mapper.selectLakeDataSourceTypeId();
  }

  /**
   * 查询数据源
   *
   * @param dataSourceId 数据源ID
   * @param typeId 分类ID
   * @return 数据源
   */
  DlmDataSourceDTO selectDataSource(String dataSourceId, String typeId) {
    DlmDataSourceDTO dataSource = mapper.selectDataSource(dataSourceId, typeId);
    if (dataSource != null) {
      DataSourceDTO dataSourceDTO = dataSourceService.selectByPrimaryKey(dataSourceId);
      dataSource.setDataSourceDTO(dataSourceDTO);
    }
    return dataSource;
  }

  /**
   * 存储接入
   *
   * @param queryMap queryMap
   * @author felix
   * @date 2020/12/7 9:53
   */
  @Transactional(rollbackFor = Exception.class)
  public void addLakeDataSource(Map<String, String> queryMap) {
    try {
      String typeId = queryMap.get("typeId");
      String dataSourceIdList = queryMap.get("dataSourceIdList");
      if (StringUtils.isBlank(dataSourceIdList) || StringUtils.isBlank(typeId)) {
        throw new BusinessException("传入的参数为null");
      }
      String[] dataSourceIds = dataSourceIdList.split(Constants.COMMA);
      for (String dataSourceId : dataSourceIds) {
        DataSourceDTO dataSourceDTO = dataSourceService.selectByPrimaryKey(dataSourceId);
        DlmDataSourceDTO dlmDataSourceDTO = new DlmDataSourceDTO();
        dlmDataSourceDTO.setId(ComUtil.getId());
        dlmDataSourceDTO.setTypeId(typeId);
        dlmDataSourceDTO.setDataSourceId(dataSourceId);
        dlmDataSourceDTO.setDataSourceStructure(dataSourceDTO.getDatasourceStructure());
        DbAdapter dbAdapter = DbAdapterUtils.getDbAdapter(dataSourceDTO.getDatasourceType());
        BaseDataSource baseDataSource = DBUtils.getBaseDataSource(dataSourceDTO);
        String versionInfo;
        try {
          versionInfo = dbAdapter.getVersion(baseDataSource);
        } catch (Exception e) {
          versionInfo = "";
        }
        dlmDataSourceDTO.setDataSourceVersion(versionInfo);
        insertSelective(dlmDataSourceDTO);
        // 记录日志
        BdpLogUtil.log4Insert(dlmDataSourceDTO);
      }
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  /**
   * 修改总容量
   *
   * @param queryMap queryMap
   * @author felix
   * @date 2020/12/7 10:11
   */
  @Transactional(rollbackFor = Exception.class)
  public void updateAvailableAmount(Map<String, String> queryMap) {

    try {
      String dataSourceId = queryMap.get("dataSourceId");
      Long availableAmount = Long.parseLong(queryMap.get("availableAmount"));
      if (StringUtils.isBlank(dataSourceId)) {
        throw new BusinessException("传入的参数为null");
      }
      // 默认传入单位是GB, 转换成B
      availableAmount = availableAmount * 1024 * 1024 * 1024;
      // 记录日志
      DlmDataSourceDTO query = new DlmDataSourceDTO();
      query.setDataSourceId(dataSourceId);
      DlmDataSourceDTO dlmDataSourceDTO = selectOne(query);
      dlmDataSourceDTO.setAvailableAmount(availableAmount);
      updateByPrimaryKey(getUpdateDto(dlmDataSourceDTO));

      String logTitle = "修改数据源：【" + dataSourceId + "】的容量为【"+ queryMap.get("availableAmount") + "GB】";
      BdpLogUtil.log("存储配置模块", logTitle, PlatformConstant.OpType.update);
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  private DlmDataSourceDTO getUpdateDto(DlmDataSourceDTO dlmDataSourceDTO) {
    DlmDataSourceDTO oldDTO = selectByPrimaryKey(dlmDataSourceDTO.getId());
    if (oldDTO == null) {
      throw new BusinessException("数据不存在");
    }
    // 记录日志
    BdpLogUtil.log4Update(dlmDataSourceDTO, oldDTO);

    oldDTO.setAvailableAmount(dlmDataSourceDTO.getAvailableAmount());
    return oldDTO;
  }

  /**
   * 移除数据源
   *
   * @param queryMap queryMap
   * @author felix
   * @date 2020/12/7 10:38
   */
  public void deleteDlmDataSource(Map<String, String> queryMap) {
    String dataSourceId = queryMap.get("dataSourceId");
    if (StringUtils.isBlank(dataSourceId)) {
      throw new BusinessException("删除失败！传入的参数为null");
    }
    try {
      // 记录日志
      DlmDataSourceDTO query = new DlmDataSourceDTO();
      query.setDataSourceId(dataSourceId);
      DlmDataSourceDTO dlmDataSourceDTO = selectOne(query);
      if (dlmDataSourceDTO == null) {
        throw new BusinessException("删除失败！对象不存在");
      }
      BdpLogUtil.log4Delete(dlmDataSourceDTO);
      delete(query);
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  /**
   * 分页获取关联数据源列表
   *
   * @param typeId 分类ID
   * @param keywords 关键词
   * @author felix
   * @date 2020/12/7 13:30
   */
  public Map<String, List<DataSourceDTO>> searchDlmDataSource(String typeId, String keywords) {
    Map<String, List<DataSourceDTO>> map = null;
    try {
      List<String> typeList =
          commonTypeService.getChildrenIds(CommonTypeEnums.STORAGE_TYPE, typeId, "");
      if (typeList == null) {
        typeList = Lists.newArrayList();
      }
      typeList.add(typeId);
      List<DataSourceDTO> list = dataSourceService.searchDlmDataSourceList(typeList, keywords);
      if (CollectionUtils.isNotEmpty(list)) {
        map = handleDataSourceList(list);
      }
      String logTitle = "查看存储配置";
      BdpLogUtil.log("存储配置模块", logTitle, PlatformConstant.OpType.select);
      return map;
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  /**
   * 获取公共数据源列表
   *
   * @param typeId 分类ID
   * @param keywords 关键词
   * @author felix
   * @date 2020/12/7 13:31
   */
  public Map<String, List<DataSourceDTO>> searchDataSource(String typeId, String keywords) {
    Map<String, List<DataSourceDTO>> map = null;
    try {
      List<String> typeList =
          commonTypeService.getChildrenIds(CommonTypeEnums.DATASOURCE_TYPE, typeId, "");
      if (typeList == null) {
        typeList = Lists.newArrayList();
      }
      typeList.add(typeId);
      List<DataSourceDTO> list = dataSourceService.searchCommonDataSourceList(typeList, keywords);
      if (CollectionUtils.isNotEmpty(list)) {
        map = handleDataSourceList(list);
      }
      return map;
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  private Map<String, List<DataSourceDTO>> handleDataSourceList(List<DataSourceDTO> list)
      throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {

    Map<String, List<DataSourceDTO>> map = new HashMap<>(2);
    List<DataSourceDTO> structureList = new ArrayList<>();
    List<DataSourceDTO> noStructureList = new ArrayList<>();

    for (DataSourceDTO bdpDasDatasourceDTO : list) {
      if (StringUtils.isNotBlank(bdpDasDatasourceDTO.getConnectionParams())) {
        BaseDataSource baseDataSource = DBUtils.getBaseDataSource(bdpDasDatasourceDTO);
        if (StringUtils.isNotBlank(baseDataSource.getPassword())) {
          baseDataSource.setPassword(
              DESUtils.decrypt(baseDataSource.getPassword()).replaceAll("(.)", "*"));
        }
        String connectionParams = JSON.toJSONString(baseDataSource);
        bdpDasDatasourceDTO.setConnectionParams(connectionParams);
      }
      if (bdpDasDatasourceDTO.getAvailableAmount() != null
          && bdpDasDatasourceDTO.getAvailableAmount() != 0L) {
        bdpDasDatasourceDTO.setAvailableAmount(
            bdpDasDatasourceDTO.getAvailableAmount() / (1024 * 1024 * 1024));
      }
      if (bdpDasDatasourceDTO.getDatasourceStructure() == 0) {
        structureList.add(bdpDasDatasourceDTO);
      }
      if (bdpDasDatasourceDTO.getDatasourceStructure() == 1) {
        noStructureList.add(bdpDasDatasourceDTO);
      }
    }

    map.put("structuredList", structureList);
    map.put("unstructuredList", noStructureList);
    return map;
  }

  /**
   * 查询存储接入分类树
   *
   * @return 分类树
   * @author felix
   * @date 2020/12/10 17:53
   */
  public List<CommonTypeDTO> findStorageCommonType() {
    try {
      List<CommonTypeDTO> list = Lists.newArrayList();
      Map<String, List<CommonTypeDTO>> map = Maps.newHashMap();
      /*CommonTypeDTO bdpDasCommonTypeDTO = new CommonTypeDTO();
      bdpDasCommonTypeDTO.setType(CommonTypeEnums.STORAGE_TYPE);
      bdpDasCommonTypeDTO.setProjectId(null);*/
      //查询通用树数据
      List<CommonTypeDTO> dataList = commonTypeService.selectByType(CommonTypeEnums.STORAGE_TYPE)
              .stream()
              .sorted(Comparator.comparing(CommonTypeDTO::getOrderBy, Comparator.nullsLast(Integer::compareTo)))
              .collect(Collectors.toList());
      if (CollectionUtils.isNotEmpty(dataList)) {
        for (CommonTypeDTO dto : dataList) {
          dto.setLeaf(0);
          dto.setIcon("folder");
          dto.setUnfolded(1);
          dto.setTypeFlag(0);
          dto.setType("-1");
        }
      }
      //查询中间分类
      List<CommonTypeDTO> storageTypeList = commonTypeService.getStorageType();
      if (CollectionUtils.isNotEmpty(storageTypeList)) {
        for (CommonTypeDTO dto : storageTypeList) {
          if ("0".equals(dto.getType())) {
            dto.setName("结构化存储");
          }
          if ("1".equals(dto.getType())) {
            dto.setName("非结构化存储");
          }
        }
      }
      //查询数据存储数据
      List<CommonTypeDTO> storageList = commonTypeService.getStorageTypeList();
      dataList.addAll(storageTypeList);
      dataList.addAll(storageList);
      if (CollectionUtils.isNotEmpty(dataList)) {
        for (CommonTypeDTO commonTypeDTO : dataList) {
          if ("-1".equals(commonTypeDTO.getParentId())) {
            list.add(commonTypeDTO);
          } else {
            if (map.containsKey(commonTypeDTO.getParentId())) {
              map.get(commonTypeDTO.getParentId()).add(commonTypeDTO);
            } else {
              List<CommonTypeDTO> commonTypeDTOList = Lists.newArrayList();
              commonTypeDTOList.add(commonTypeDTO);
              map.put(commonTypeDTO.getParentId(), commonTypeDTOList);
            }
          }
        }
      }
      listConvert(list, map);
      return list;
    } catch (Exception e) {
      throw new BusinessException(e.getMessage(), e);
    }
  }

  private void listConvert(List<CommonTypeDTO> list, Map<String, List<CommonTypeDTO>> map) {
    for (CommonTypeDTO commonTypeDTO : list) {
      List<CommonTypeDTO> commonTypeDTOList = map.get(commonTypeDTO.getId());
      if (CollectionUtils.isNotEmpty(commonTypeDTOList)) {
        listConvert(commonTypeDTOList, map);
        commonTypeDTO.setChildren(commonTypeDTOList);
      } else {
        if (commonTypeDTO.getTypeFlag() == 1) {
          String parentId = commonTypeDTO.getParentId().split(Constants.SUBTRACT_STRING)[0];
          commonTypeDTO.setParentId(parentId);
        }
        commonTypeDTO.setChildren(null);
      }
    }
  }

  /**
   * 通过分类ID查询数据湖关联数据源
   *
   * @param typeId 分类ID
   * @param type 数据源类型
   * @return 关联数据源
   */
  public List<DataSourceDTO> getDataSourceListByTypeIdAndType(String typeId, Integer type) {
    return mapper.getDataSourceListByTypeIdAndType(typeId, type);
  }
}
